package com.hnucm.a1transitionbutton.button;

import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.drawable.GradientDrawable;
import android.util.AttributeSet;
import android.view.animation.LinearInterpolator;

import com.hnucm.a1transitionbutton.R;


/**
 * @author starry
 * 自定义登录按钮
 */

public class MyButton extends androidx.appcompat.widget.AppCompatButton {

    //初始的长宽
    private int width;
    private int height;

    //定义shape属性
    private GradientDrawable backDrawable;

    private boolean isMorphing;
    private int startAngle;

    private Paint paint;

    private ValueAnimator arcValueAnimator;

    //构造函数
    public MyButton(Context context) {
        super(context);
        init(context);
    }

    public MyButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public MyButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    //初始化按钮
    private void init(Context context) {
        isMorphing=false;

        backDrawable=new GradientDrawable();
        int colorDrawable=context.getColor(R.color.skyBlue);//按钮的颜色
        backDrawable.setColor(colorDrawable);
        backDrawable.setCornerRadius(120);//默认圆角
        setBackground(backDrawable);

        setText("登陆");//文字
        setTextSize(20);//文字大小

        //初始化画笔
        paint=new Paint();
        paint.setColor(getResources().getColor(R.color.white));
        paint.setStrokeWidth(4);
        paint.setStyle(Paint.Style.STROKE);
        paint.setTextSize(2);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthMode=MeasureSpec.getMode(widthMeasureSpec);
        int widthSize=MeasureSpec.getSize(widthMeasureSpec);
        int heightMode=MeasureSpec.getMode(heightMeasureSpec);
        int heightSize=MeasureSpec.getSize(heightMeasureSpec);
        if (widthMode==MeasureSpec.EXACTLY){
            width=widthSize;
        }
        if (heightMode==MeasureSpec.EXACTLY){
            height=heightSize;
        }
    }

    public void startAnim(){
        isMorphing=true;

        setText("");
        /**
         * ValueAnimator：这个动画是针对属性的值进行动画的 ，
         * 不会对UI造成改变，不能直接实现动画效果。
         * 需要通过对动画的监听去做一些操作，
         * 在监听中将这个值设置给对应的属性，对应的属性才会改变。
         * width和height对应绘制按钮的宽和高。
         * 添加UpdateListener监听可以检测到每次值的变化情况，
         * 每次UpdateListener检测到值变化时通过
         * backDrawable.setBounds重新绘制backDrawable的范围。

         */
        ValueAnimator valueAnimator=ValueAnimator.ofInt(width,height);


        valueAnimator.addUpdateListener(animation -> {
            int value= (int) animation.getAnimatedValue();
            int leftOffset=(width-value)/2;
            int rightOffset=width-leftOffset;
            //由最初的长条范围变化为可绘制圆的范围
            backDrawable.setBounds(leftOffset,0,rightOffset,height);
        });
        //cornerRadius从最初设置的120变为height的一半。
        ObjectAnimator objectAnimator=ObjectAnimator.ofFloat(backDrawable,"cornerRadius",120,height/2);

        /**
         * 既然bound和cornerRadius同时改变，
         * 是不是两个Animator一起start才可以实现呢？
         * 有一个类叫AnimatorSet，顾名思义就是Animator的集合，
         * 通过它就可以使多个动画协调工作。
         * playTogether的方法中可以放入多个Animator,
         * 可以使多个动画协调工作。调用start后，多个动画开始工作
         */
        AnimatorSet animatorSet=new AnimatorSet();
        animatorSet.setDuration(500);
        animatorSet.playTogether(valueAnimator,objectAnimator);
        animatorSet.start();

        //画中间的白色圆圈
        showArc();
    }
    public void gotoNew(){
        isMorphing=false;

        arcValueAnimator.cancel();
        setVisibility(GONE);

    }
    public void regainBackground(){
        setVisibility(VISIBLE);
        backDrawable.setBounds(0,0,width,height);
        backDrawable.setCornerRadius(24);
        setBackground(backDrawable);
        setText("登陆");
        isMorphing=false;
    }



    private void showArc() {
        arcValueAnimator=ValueAnimator.ofInt(0,1080);
        arcValueAnimator.addUpdateListener(animation -> {
            startAngle= (int) animation.getAnimatedValue();
            invalidate();
        });
        /**
         * ValueAnimatro可以设置插值器Interpolator
         * 插值器系统定义了好几种，有accelerated(加速)，
         * decelerated(减速),repeated(重复),bounced(弹跳)
         * LinearInterpolator(匀速)
         */
        arcValueAnimator.setInterpolator(new LinearInterpolator());
        arcValueAnimator.setRepeatCount(ValueAnimator.INFINITE);
        arcValueAnimator.setDuration(3000);
        arcValueAnimator.start();


    }

    /**
     * 利用canvas.drawArc这个方法就可以画弧。
     */
    @Override
    protected void onDraw(final Canvas canvas) {
        super.onDraw(canvas);

        if (isMorphing==true){
            final RectF rectF=new RectF(getWidth()*5/12,
                    getHeight()/7,getWidth()*7/12,
                    getHeight()-getHeight()/7);
            /**
             * drawArc的第二个参数为圆弧的起始角度，
             *  只需要不断改变这个角度，就会形成旋转的动画。
             *  把drawArc中第二个参数换成startAngle，在每次值更新后都重绘界面。
             *  这样圆弧的起始点就一直变化，形成了旋
             * 转效果。设置animator无限循环，这样效果就实现了，
             */
            canvas.drawArc(rectF,startAngle,270,false,paint);
        }
    }
}